package org.framework.lazy.cloud.network.heartbeat.server.context;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.context.SocketApplicationListener;
import org.framework.lazy.cloud.network.heartbeat.server.netty.permeate.tcp.filter.NettyTcpServerFilter;
import org.framework.lazy.cloud.network.heartbeat.server.properties.ServerNodeProperties;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class NettyTcpServerSocketApplicationListener implements SocketApplicationListener {

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private final NettyTcpServerFilter nettyTcpServerFilter;// 通道业务处理
    private final ServerNodeProperties serverNodeProperties;
    private ChannelFuture channelFuture;

    public NettyTcpServerSocketApplicationListener(NettyTcpServerFilter nettyTcpServerFilter, ServerNodeProperties serverNodeProperties) {
        this.nettyTcpServerFilter = nettyTcpServerFilter;
        this.serverNodeProperties = serverNodeProperties;
    }

    /**
     * 运行
     *
     * @throws InterruptedException
     */
    @Override
    public void doRunning() throws Exception {
        try {
            ServerNodeProperties.Tcp tcp = serverNodeProperties.getTcp();
            Integer tcpPort = tcp.getPort();
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // 给服务端channel设置属性
                    // 设置读缓冲区为2M
                    .childOption(ChannelOption.SO_RCVBUF, 2048 * 1024)
                    // 设置写缓冲区为1M
                    .childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)

                    .childOption(ChannelOption.SO_KEEPALIVE, true)
//                    .childOption(ChannelOption.TCP_NODELAY, false)
                    .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
//                    .childOption(ChannelOption.RCVBUF_ALLOCATOR, new NettyRecvByteBufAllocator(1024 * 1024))//用于Channel分配接受Buffer的分配器 默认AdaptiveRecvByteBufAllocator.DEFAULT
                    .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))

                    .childHandler(nettyTcpServerFilter);
            channelFuture = b.bind(tcpPort).sync();

            channelFuture.addListener((ChannelFutureListener) channelFuture -> {
                // 服务器已启动
                log.info("TCP 服务器启动成功【{}】", tcpPort);
            });
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("启动TCP 失败", e);
        } finally {
            destroy();
            // 服务器已关闭
            log.warn("TCP 服务关闭");
        }
    }

    @PreDestroy
    @Override
    public void destroy() {
        if (channelFuture != null) {
            channelFuture.channel().close().syncUninterruptibly();
        }
        if ((bossGroup != null) && (!bossGroup.isShutdown())) {
            bossGroup.shutdownGracefully();
        }
        if ((workerGroup != null) && (!workerGroup.isShutdown())) {
            workerGroup.shutdownGracefully();
        }
    }


}